package com.whale.web.json.tree;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.ui.Model;

import com.whale.constants.MenuGroupConstants;
import com.whale.kernel.domain.HtmlPage;
import com.whale.kernel.model.pagination.PagedList;
import com.whale.kernel.model.pagination.Step;
import com.whale.kernel.model.tree.HtmlMenuNode;
import com.whale.kernel.model.tree.Nodal;
import com.whale.kernel.service.HtmlMenuService;
import com.whale.kernel.service.HtmlPageService;
import com.whale.kernel.utils.TreeUtils;

public class MenuTreeJsonProcessor {

	private final HtmlPageService htmlPageService;
	private final HtmlMenuService htmlMenuService;

	/**
	 * Ограничение уровня загрузки узлов
	 */
	private final static int MENU_MAX_LEVEL = 4;

	public MenuTreeJsonProcessor(HtmlPageService htmlPageService,
			HtmlMenuService htmlMenuService) {
		this.htmlPageService = htmlPageService;
		this.htmlMenuService = htmlMenuService;
	}

	public JSONObject getLeafPageJSON(Long menuId) throws JSONException {
		Step step = new Step(10, 0);
		PagedList<HtmlPage> pagedLeafs = htmlPageService.findHtmlPagesByMenuId(
				menuId, new Step(10, 0));
		JSONObject leafPage = new JSONObject();
		leafPage.put("pageNum", 1);
		leafPage.put("offset", step.getOffset());
		leafPage.put("total", pagedLeafs.getTotal());
		JSONObject leafs = new JSONObject();
		for (HtmlPage htmlPage : pagedLeafs.getResult()) {
			leafs.put(htmlPage.getPageId(), Arrays.asList(htmlPage.getTitle(),
					htmlPage.getModificationDate().toString()));
		}
		leafPage.put("leafs", leafs);
		return leafPage;
	}

	public JSONObject getMenuNodeJSON(Nodal<HtmlMenuNode> node, Map<Long, HtmlMenuNode> treeNodes, int maxLevel)
			throws JSONException {
		JSONObject menuNode = new JSONObject();
		menuNode.put("title", node.getNodeName());
		menuNode.put("nodeKey", node.getNodeKey());
		if (node.getLocalNodeLevel() >= maxLevel) {
			menuNode.put("fakeNode", true);
			return menuNode;
		}
		
		menuNode.put("leafPage", getLeafPageJSON(node.getId()));
		List<HtmlMenuNode> childNodes = TreeUtils.getChildNodes(node.getId(), treeNodes);
		if (node.getLocalNodeLevel() == maxLevel-1 && !childNodes.isEmpty()) {
			// флаг - данную ветку нужно ли под-грузить с сервера
			menuNode.put("requireLoading", true);
		}
		
		menuNode.put("subnodes",
				getChildMenusNodeJSON(childNodes, treeNodes, maxLevel));
		return menuNode;
	}

	public JSONArray getChildMenusNodeJSON(List<HtmlMenuNode> childNodes, Map<Long, HtmlMenuNode> treeNodes,
			int maxLevel) throws JSONException {
		JSONArray subnodes = new JSONArray();
		for (HtmlMenuNode child : childNodes) {
			subnodes.put(
					getMenuNodeJSON(child, treeNodes, maxLevel));
		}
		return subnodes;
	}

	public void populateTreeMenu(Model model) throws JSONException {
		// MENU_MAX_LEVEL + 1: означает что из базы достаем на один уровень
		// больше, для того что бы определить необходимость подгружать дочерние
		// узлы
		Map<Long, HtmlMenuNode> treeNodes = htmlMenuService.getTreeRootMenus(
				MenuGroupConstants.USER_MENU_GROUP_ID, MENU_MAX_LEVEL);
		List<HtmlMenuNode> rootNodes = TreeUtils.getRootNodes(treeNodes);
		JSONObject topNodeJSON = getMenuNodeJSON(rootNodes.get(0), treeNodes, MENU_MAX_LEVEL);
		String topNodeStr = (new JSONObject()).put("topnode", topNodeJSON).toString();
		model.addAttribute("topNodeJSON", topNodeStr);
	}

	public JSONObject feedChildMenus(Long nodeId) throws JSONException {
		Map<Long, HtmlMenuNode> treeNodes = htmlMenuService.getChildMenus(nodeId, MENU_MAX_LEVEL);
		List<HtmlMenuNode> rootNodes = TreeUtils.getRootNodes(treeNodes);
		return getMenuNodeJSON(rootNodes.get(0), treeNodes, MENU_MAX_LEVEL);
	}
	
	public JSONObject feedTreeScopeMenus(Long nodeId) throws JSONException {
		Map<Long, HtmlMenuNode> treeNodes = htmlMenuService.getTreeScopeMenus(nodeId, MENU_MAX_LEVEL);
		List<HtmlMenuNode> rootNodes = TreeUtils.getRootNodes(treeNodes);
		return getMenuNodeJSON(rootNodes.get(0), treeNodes, MENU_MAX_LEVEL);
	}
}
